<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../libs/system.js"></script>
    <script>
        System.import('../libs/cc.js');
    </script>

    <script>

        // 验证初等变换
        function asset(value,msg){
            if(!value){
                throw new Error(msg);
            }
        }

        window.onload = function () {

            cc.mat3 = function(){
                return new cc.Mat3();
            };

            let A = cc.mat3();
            cc.Mat3.set(A,3,1,7,6,2,4,2,3,1);

            // 初等矩阵
            // 1. 交换两行
            let r12 = change_row(1,2);
            let inv_r12 = cc.mat3();
            cc.Mat3.invert(inv_r12,r12);

            let X = cc.mat3();
            cc.Mat3.multiply(X,r12,A);
            console.log('X:',X);

            let t1 = add_ki_to_j(-3,1,2);
            let t2 = add_ki_to_j(-7,1,3);

            let inv_t1 = cc.mat3();
            let inv_t2 = cc.mat3();
            cc.Mat3.invert(inv_t1,t1);
            cc.Mat3.invert(inv_t2,t2);

            let Y = cc.mat3();
            cc.Mat3.multiply(Y,t2,t1);
            cc.Mat3.multiply(Y,Y,X);
            console.log('Y:',Y);

            // 交换列
            let c23 = change_row(2,3);
            let inv_c23 = cc.mat3();
            cc.Mat3.invert(inv_c23,c23);

            cc.Mat3.multiply(Y,Y,c23);
            console.log('Y:',Y);

            let t3 = add_ki_to_j(3/7,2,1);
            let inv_t3 = cc.mat3();
            cc.Mat3.invert(inv_t3,t3);

            cc.Mat3.multiply(Y,t3,Y);
            console.log('Y:',Y);

            let t4 = add_ki_to_j(-20/7,2,3);
            let inv_t4 = cc.mat3();
            cc.Mat3.invert(inv_t4,t4);
            cc.Mat3.multiply(Y,t4,Y);
            console.log('Y:',Y);

            let t5 = add_ki_to_j(1/5,3,1);
            let inv_t5 = cc.mat3();
            cc.Mat3.invert(inv_t5,t5);
            cc.Mat3.multiply(Y,t5,Y);
            console.log('Y:',Y);

            // k
            let t6 = kRow(-1/7,2);
            let inv_t6 = cc.mat3();
            cc.Mat3.invert(inv_t6,t6);
            cc.Mat3.multiply(Y,t6,Y);
            console.log('Y:',Y);

            let t7 = kRow(-1/10,3);
            let inv_t7 = cc.mat3();
            cc.Mat3.invert(inv_t7,t7);
            cc.Mat3.multiply(Y,t7,Y);
            console.log('Y:',Y);


            //---------------------
            //
            console.log('开始计算逆....');
            let inv_A = cc.mat3();
            cc.Mat3.invert(inv_A,A);
            console.log('inv_A:',inv_A);

            let P = cc.mat3();
            cc.Mat3.multiply(P,t7,t6);
            cc.Mat3.multiply(P,P,t5);
            cc.Mat3.multiply(P,P,t4);
            cc.Mat3.multiply(P,P,t3);
            cc.Mat3.multiply(P,P,t2);
            cc.Mat3.multiply(P,P,t1);
            cc.Mat3.multiply(P,P,r12);

            let Q = c23;

            let QP = cc.mat3();
            cc.Mat3.multiply(QP,Q,P);
            console.log('QP:',QP);

            let PQ = cc.mat3();
            cc.Mat3.multiply(PQ,P,Q);
            console.log('PQ:',PQ);

        };


        /**
         * 交换 第i j行. 的矩阵
         * 其实是交换 行索引为  i-1 和 j-1  的两行
         */
        function change_row(i,j) {
            asset(i !== j, 'i 不应该等于 j');
            let ret = cc.mat3();

            let arr_i = getRow(ret,i - 1);
            let arr_j = getRow(ret, j - 1);

            setRow(ret,i - 1,arr_j);
            setRow(ret,j - 1,arr_i);
            return ret;
        }

        function change_col(i,j) {
            asset(i !== j, 'i 不应该等于 j');
            let ret = cc.mat3();

            let arr_i = getColumn(ret,i - 1);
            let arr_j  = getColumn(ret,j - 1);
            setColumn(ret, i - 1,arr_j);
            setColumn(ret, j - 1, arr_i);
            return ret;
        }

        /**
         * 行 i x k + j -> j
         *  i,j 不是索引.
         */
        function add_ki_to_j(k,i,j) {
            asset(i !== j, 'i 不应该等于 j');
            asset( k !== 0, 'k 不能为 0');
            let ret = cc.mat3();
            let arr_i = getRow(ret,i - 1);
            let arr_ki = arr_i.map(v=>{return k * v});
            let arr_j = getRow(ret,j - 1);
            let final_row_j = arr_j.map((v,n)=>{return v + arr_ki[n]});
            setRow(ret,j-1,final_row_j);
            return ret;
        }

        /**
         *
         * @param m  cc.Mat3
         * @param idx 表示行索引 范围为 [0,2]
         * @return {*[]}
         */
        function getRow(m,idx) {
            switch (idx) {
                case 0:
                    return [m.m00,m.m03,m.m06];
                case 1:
                    return [m.m01,m.m04,m.m07];
                case 2:
                    return [m.m02,m.m05,m.m08];
            }
        }

        function getColumn(m,idx) {
            switch (idx) {
                case 0:
                    return [m.m00,m.m01,m.m02];
                case 1:
                    return [m.m03,m.m04,m.m05];
                case 2:
                    return [m.m06,m.m07,m.m08];
            }
        }

        function setColumn(m,idx,arr) {
            switch (idx) {
                case 0:
                    m.m00 = arr[0];
                    m.m01 = arr[1];
                    m.m02 = arr[2];
                    break;
                case 1:
                    m.m03 = arr[0];
                    m.m04 = arr[1];
                    m.m05 = arr[2];
                    break;
                case 2:
                    m.m06 = arr[0];
                    m.m07 = arr[1];
                    m.m08 = arr[2];
                    break;
            }
        }

        /**
         * 给矩阵m 设置值
         * @param m
         * @param idx
         * @param arr
         */
        function setRow(m,idx,arr) {
            switch (idx) {
                case 0:
                    m.m00 = arr[0];
                    m.m03 = arr[1];
                    m.m06 = arr[2];
                    break;
                case 1:
                    m.m01 = arr[0];
                    m.m04 = arr[1];
                    m.m07 = arr[2];
                    break;
                case 2:
                    m.m02 = arr[0];
                    m.m05 = arr[1];
                    m.m08 = arr[2];
                    break;
            }
        }

        function kRow(k,i) {
            let ret = cc.mat3();
            let arr_i = getRow(ret,i - 1);
            let arr_ki = arr_i.map(v=>{return k * v;});
            setRow(ret,i - 1,arr_ki);
            return ret;
        }



        //====================
        // 求初等矩阵的逆


    </script>
</head>
<body>

</body>
</html>
